#include "Ctrl/SelectionModel.hpp"
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/foreach.hpp>
#include <algorithm>
#include <cassert>

namespace Ctrl
{


// ---------------------------------------------------------------------------------------------------------------------

void SelectionModel::mergeSelection( const std::list< Model::CaseEntity*>& selected )
{
	std::size_t oldSelectionChange = this->size();
	BOOST_FOREACH( Model::CaseEntity* pEntity, selected)
	{
		this->mergeSelection( pEntity);
	}
	if( oldSelectionChange == this->size())
	{
		onSelectionChanged_( *this);
	}
}

// ---------------------------------------------------------------------------------------------------------------------

void SelectionModel::mergeSelection( Model::CaseEntity* pSelected )
{
	assert( NULL != pSelected);

	std::size_t oldSelectionChange = this->size();
	if( !this->isSelected( pSelected))
	{	
		this->insert( pSelected);
	}
	if( oldSelectionChange == this->size())
	{
		onSelectionChanged_( *this);
	}
}

// ---------------------------------------------------------------------------------------------------------------------

void SelectionModel::replaceSelection( std::list< Model::CaseEntity*>& newSelection )
{
	using namespace boost::lambda;
	selection_.clear();
	BOOST_FOREACH( Model::CaseEntity* pEntity, newSelection)
	{
		this->mergeSelection( pEntity);
	}
	onSelectionChanged_( *this);
}

// ---------------------------------------------------------------------------------------------------------------------

void SelectionModel::replaceSelection( Model::CaseEntity* pSelected )
{
	selection_.clear();
	this->insert( pSelected);
	onSelectionChanged_( *this);
}

// ---------------------------------------------------------------------------------------------------------------------

void SelectionModel::unselect( std::list< Model::CaseEntity*>& unselected )
{
	std::size_t oldSelectionChange = this->size();

	BOOST_FOREACH( Model::CaseEntity* pEntity, unselected)
	{
		this->unselect( pEntity);
	}

	if( oldSelectionChange == this->size())
	{
		onSelectionChanged_( *this);
	}
}

// ---------------------------------------------------------------------------------------------------------------------

void SelectionModel::unselect( Model::CaseEntity* pUnselected )
{
	assert( NULL != pUnselected);
	std::size_t oldSelectionChange = this->size();

	SelectionIterator iter = selection_.find( pUnselected);
	if( iter != selection_.end())
	{
		selection_.erase( iter);
	}
	
	if( oldSelectionChange == this->size())
	{
		onSelectionChanged_( *this);
	}
}

// ---------------------------------------------------------------------------------------------------------------------

void SelectionModel::clear()
{
	std::size_t oldSelectionChange = this->size();
	selection_.clear();
	if( oldSelectionChange == this->size())
	{
		onSelectionChanged_( *this);
	}
}

// ---------------------------------------------------------------------------------------------------------------------

bool SelectionModel::isEmpty() const
{
	return selection_.empty();
}

// ---------------------------------------------------------------------------------------------------------------------

bool SelectionModel::isSelected( Model::CaseEntity* pEntityToCheck ) const
{
	return selection_.end() != selection_.find( pEntityToCheck);
}

// ---------------------------------------------------------------------------------------------------------------------

void SelectionModel::insert( Model::CaseEntity* pSelected )
{
	assert( NULL != pSelected);
	assert( selection_.end() == selection_.find( pSelected));
	selection_.insert( pSelected);
}

// ---------------------------------------------------------------------------------------------------------------------

void SelectionModel::subscribeToSelectionChanged( const SelectionChangedSlot::slot_type& slot )
{
	onSelectionChanged_.connect( slot);
}

} // namespace Ctrl
